package com.itheima.app.mapper;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.itheima.service.mongo.CommentService;
import com.itheima.util.ConstantUtil;
import com.itheima.vo.CommentVo;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.bson.types.ObjectId;
import com.itheima.app.interceptor.UserHolder;
import com.itheima.autoconfig.oss.OssTemplate;
import com.itheima.domain.db.UserInfo;
import com.itheima.domain.mongo.Comment;
import com.itheima.domain.mongo.Movement;
import com.itheima.service.db.UserInfoService;
import com.itheima.service.mongo.MovementService;
import com.itheima.util.DateFormatUtil;
import com.itheima.vo.MovementVo;
import com.itheima.vo.PageBeanVo;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class MovementManager {

    @Autowired
    private OssTemplate ossTemplate;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Reference
    private MovementService movementService;

    @Reference
    private CommentService commentService;

    @Reference
    private UserInfoService userInfoService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private MQMovementManager mqMovementManager;

    //保存动态
    public void saveMovement(Movement movement, MultipartFile[] imageContent) throws IOException {
        //1. 获取到用户信息
        Long userId = UserHolder.getUser().getId();

        //2. 封装保存的动态对象
        movement.setUserId(userId);//用户id
        movement.setId(ObjectId.get());//提前生成一个动态的Id
        movement.setState(0);//默认状态，未审核
        movement.setCreated(System.currentTimeMillis());//创建时间(当前时间毫秒数)
        movement.setSeeType(1);//todo 公开
        // 阿里云文件上传
        List<String> files = new ArrayList<>();
        if (imageContent != null && imageContent.length > 0) {
            for (MultipartFile multipartFile : imageContent) {
                String filePath = ossTemplate.upload(multipartFile.getOriginalFilename(), multipartFile.getInputStream());
                files.add(filePath);
            }
        }
        movement.setMedias(files);

        //3. 执行动态保存
        movementService.save(movement);

        //4. 向mq投递一个保存动态的消息
        rocketMQTemplate.convertAndSend("tanhua-movement", movement.getId().toHexString());

        //5. 向mq投递消息(大数据推荐)
        mqMovementManager.sendMovementMsg(movement.getId().toHexString(),MQMovementManager.MOVEMENT_PUBLISH);
    }

    //查询我的动态
    public PageBeanVo findMyMovement(Long userId, Integer pageNum, Integer pageSize) {
        //1.调用service分页查询
        PageBeanVo pageBeanVo = movementService.findMyMovement(userId,pageNum,pageSize);
        //2.组装返回值
        //2.1 获取到返回值中的movement列表
        List<Movement> movementList =(List<Movement>) pageBeanVo.getItems();
        List<MovementVo> movementVoList = new ArrayList<>();//临时集合

        if(CollectionUtil.isNotEmpty(movementList)){
            for (Movement movement : movementList) {
                //2.2 创建movementVo,来封装前端需要的返回值对象中的集合部分
                MovementVo movementVo = new MovementVo();
                //2.3 设置movementVo中动态发布者的信息
                UserInfo userInfo = userInfoService.findById(movement.getUserId());
                BeanUtils.copyProperties(userInfo,movementVo);//复制了头像 昵称 性别  年龄
                if(StringUtils.isNotEmpty(userInfo.getTags())){
                    movementVo.setTags(userInfo.getTags().split(","));
                }
                //2.4 设置movementVo中动态的信息
                BeanUtils.copyProperties(movement,movementVo);//复制了用户id 文字动态 点赞  喜欢 评论数
                if(CollectionUtil.isNotEmpty(movement.getMedias())){
                    movementVo.setImageContent(movement.getMedias().toArray(new String[]{}));
                }

                movementVo.setDistance("10km");//todo 百度地图之后再处理

                movementVo.setCreateDate(DateFormatUtil.format(new Date(movement.getCreated())));

                //2.5将movementVo放入临时集合
                movementVoList.add(movementVo);
            }
        }

        //3 替换分页对象中的items(List<Movement>---->List<MovementVo>)
        pageBeanVo.setItems(movementVoList);

        System.out.println(pageBeanVo);
        //4.返回结果
        return pageBeanVo;
    }


    //查询我的好友动态
    public PageBeanVo findFriendMovement(Integer pageNum, Integer pageSize) {
        //1. 获取登录用户的id
        Long userId = UserHolder.getUser().getId();

        //2. 调用service分页查询好友的动态
        PageBeanVo pageBeanVo = movementService.findFriendMovement(userId, pageNum, pageSize);

        //3. 组装返回数据
        //3.1 获取到返回值中的movement列表
        List<Movement> movementList = (List<Movement>) pageBeanVo.getItems();
        List<MovementVo> movementVoList = new ArrayList<>();//临时集合

        if (CollectionUtil.isNotEmpty(movementList)) {
            for (Movement movement : movementList) {
                //3.2 创建movementVo,来封装前端需要的返回值对象中的集合部分
                MovementVo movementVo = new MovementVo();

                //3.3 设置movementVo中动态发布者的信息
                UserInfo userInfo = userInfoService.findById(movement.getUserId());//根据动态发布人id查询其详细信息
                movementVo.setUserInfo(userInfo);

                //3.4 设置movementVo中动态的信息
                movementVo.setMovement(movement);

                //3.5 将movementVo放入临时集合
                movementVoList.add(movementVo);

                //3.6 获取当前用户是否对当前动态点过赞
                if (stringRedisTemplate.hasKey(StrUtil.format(ConstantUtil.MOVEMENT_LIKE, userId, movement.getId()))) {
                    movementVo.setHasLiked(1); //点赞
                } else {
                    movementVo.setHasLiked(0); //未点赞
                }
            }
        }

        //3 替换分页对象中的items(List<Movement>---->List<MovementVo>)
        pageBeanVo.setItems(movementVoList);

        //4 返回结果
        return pageBeanVo;
    }


    //查询推荐的动态
    public PageBeanVo findRecommendMovement(Integer pageNum, Integer pageSize) {
        //1获取用户Id
        Long userId = UserHolder.getUser().getId();
        //2根据用户id进行分页查询推荐动态
        PageBeanVo pageBeanVo=movementService.findRecommendMovement(userId,pageNum,pageSize);

        //3封装返回对象
        //3.1 获取到返回值中的movement列表
        List<Movement> movementList =(List<Movement>) pageBeanVo.getItems();
        //创建一个临时集合
        List<MovementVo> movementVoList = new ArrayList<>();

        if(CollectionUtil.isNotEmpty(movementList)){
            for (Movement movement : movementList) {
                //3.2 创建movementVo,来封装前端需要的返回值对象中的集合部分
                MovementVo movementVo = new MovementVo();
                //3.3 设置movementVo中动态发布者的信息
                //根据动态发布人id查询其详细信息
                UserInfo userInfo = userInfoService.findById(movement.getUserId());
                movementVo.setUserInfo(userInfo);
                //3.4 设置movenmentVo中的动态信息
                movementVo.setMovement(movement);
                //3.5将movenmentVo放入集合
                movementVoList.add(movementVo);

                //3.6设置是否已经点赞
                if (stringRedisTemplate.hasKey(StrUtil.format(ConstantUtil.MOVEMENT_LIKE, userId, movement.getId()))) {
                    movementVo.setHasLiked(1); //点赞
                } else {
                    movementVo.setHasLiked(0); //未点赞
                }

                //3.7设置是否喜欢
                if (stringRedisTemplate.hasKey(StrUtil.format(ConstantUtil.MOVEMENT_LOVE, userId, movement.getId()))) {
                    movementVo.setHasLoved(1);
                } else {
                    movementVo.setHasLoved(0);
                }
            }
        }
        //4 替换分页对象中的items(List<Movement>---->List<MovementVo>)
        pageBeanVo.setItems(movementVoList);
        //5 返回结果
        return pageBeanVo;
    }

    //对动态进行点赞
    public Integer movementLike(String movementId) {
        // 1组装comment对象
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));//动态id
        comment.setCommentType(1);//点赞
        comment.setUserId(UserHolder.getUser().getId());

        //2.调用service完成点赞
        Integer count = commentService.saveMovementComment(comment);

        //3. 向redis中记录点赞操作
        stringRedisTemplate.opsForValue().set(StrUtil.format(ConstantUtil.MOVEMENT_LIKE, UserHolder.getUser().getId(), movementId), "1");

        //向mq投递消息(大数据推荐)
        mqMovementManager.sendMovementMsg(movementId, MQMovementManager.MOVEMENT_LIKE);
        return count;
    }

    //对动态进行取消点赞
    public Integer movementDislike(String movementId) {
        //1. 组装comment对象
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));//动态id
        comment.setCommentType(1);//点赞
        comment.setUserId(UserHolder.getUser().getId());//操作人id

        //2. 调用service完成取消点赞
        Integer count = commentService.deleteMovementComment(comment);

        //3. 向redis中删除点赞操作
        stringRedisTemplate.delete(StrUtil.format(ConstantUtil.MOVEMENT_LIKE, UserHolder.getUser().getId(), movementId));

        //向mq投递消息(大数据推荐)
        mqMovementManager.sendMovementMsg(movementId, MQMovementManager.MOVEMENT_DISLIKE);
        return count;
    }

    //对动态进行喜欢
    public Integer movementLove(String movementId) {
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));//动态id
        comment.setCommentType(3);//喜欢
        comment.setUserId(UserHolder.getUser().getId());
        //2.调用service完成点赞
        Integer count = commentService.saveMovementComment(comment);

        //3. 向redis中记录点赞操作
        stringRedisTemplate.opsForValue().set(StrUtil.format(ConstantUtil.MOVEMENT_LOVE, UserHolder.getUser().getId(), movementId), "1");

        //向mq投递消息(大数据推荐)
        mqMovementManager.sendMovementMsg(movementId, MQMovementManager.MOVEMENT_LOVE);
        return count;
    }

    //对动态进行取消喜欢
    public Integer movementUnlove(String movementId) {
        //1. 组装comment对象
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));//动态id
        comment.setCommentType(3);//喜欢
        comment.setUserId(UserHolder.getUser().getId());//操作人id

        //2. 调用service完成取消喜欢
        Integer count = commentService.deleteMovementComment(comment);

        //3. 向redis中删除喜欢操作
        stringRedisTemplate.delete(StrUtil.format(ConstantUtil.MOVEMENT_LOVE, UserHolder.getUser().getId(), movementId));

        //向mq投递消息(大数据推荐)
        mqMovementManager.sendMovementMsg(movementId, MQMovementManager.MOVEMENT_DISLOVE);
        return count;
    }


    //单条动态
    public MovementVo findMovementById(String movementId) {
        //1. 调用service根据动态id查询动态详情
        Movement movement = movementService.findMyMovementById(movementId);

        //2. 动态详情中获取发布者id,根据发布者id查询发布者信息
        Long userId = movement.getUserId();//获取动态发布者的id
        UserInfo userInfo = userInfoService.findById(userId);

        //3. 组装返回数据
        MovementVo movementVo = new MovementVo();
        movementVo.setUserInfo(userInfo);//用户部分
        movementVo.setMovement(movement);//动态部分

        //向mq投递消息(大数据推荐)
        mqMovementManager.sendMovementMsg(movementId, MQMovementManager.MOVEMENT_BROWSE);
        return movementVo;
    }

    //查询指定动态的评论列表
    public PageBeanVo findMovementComment(String movementId, Integer pageNum, Integer pageSize) {
        //1. 调用commentservice查询列表
        PageBeanVo pageBeanVo =  commentService.findCommentByMovement(movementId,pageNum,pageSize);
       //2. 组装返回结果
        List<Comment> commentList = (List<Comment>) pageBeanVo.getItems();
        //创建临时集合
        List<CommentVo> commentVoList = new ArrayList<>();

        if(CollectionUtil.isNotEmpty(commentList)){
            for (Comment comment : commentList) {
                //3.创建commentVo 来封装前端返回的对象中的集合部分
                CommentVo commentVo = new CommentVo();
                //3-1 设置评论信息
                commentVo.setId(comment.getId().toHexString());//评论id
                commentVo.setContent(comment.getContent());//评论内容
                commentVo.setCreateDate(DateFormatUtil.format(new Date(comment.getCreated())));//评论发布时间
                //3-2 设置评论发布人的信息
                Long userId = comment.getUserId();//获取评论者Id
                UserInfo userInfo = userInfoService.findById(userId);//评论人信息
                commentVo.setAvatar(userInfo.getAvatar());//评论者头像
                commentVo.setNickname(userInfo.getNickname());//评论者昵称

                //查看是否点赞动态评论
                boolean s = stringRedisTemplate.hasKey(StrUtil.format(ConstantUtil.MOVEMENT_COMMENT_LIKE, UserHolder.getUser().getId(), comment.getId()));
                if(s){
                    commentVo.setHasLiked(1);//点赞
                }else {
                    commentVo.setHasLiked(0);//没点赞
                }

                //3-3 存储到临时集合
                commentVoList.add(commentVo);
            }
        }
         //4 替换分页对象中的items(List<Comment>---->List<CommentVo>)
        pageBeanVo.setItems(commentVoList);

        //5.返回结果
        return pageBeanVo;
    }

    //对动态进行语言评论
    public Integer saveComment(String movementId, String commentContent) {
        //1.组装comment对象
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));//动态id
        comment.setCommentType(2);//评论
        comment.setUserId(UserHolder.getUser().getId());//评论人
        comment.setContent(commentContent);//评论内容
        //2.调用service保存评论
        Integer count = commentService.saveMovementComment(comment);

        //向mq投递消息(大数据推荐)
        mqMovementManager.sendMovementMsg(movementId, MQMovementManager.MOVEMENT_COMMENT);
        return count;
    }

    //动态评论点赞
    public Integer movementCommentLike(String commentId) {
        // 1组装comment对象
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(commentId));//动态评论id
        comment.setCommentType(1);//点赞
        comment.setUserId(UserHolder.getUser().getId());

        //2.调用service完成喜欢
        Integer count = commentService.saveMovementCommentLike(comment);

        //3. 向redis中记录喜欢操作
        stringRedisTemplate.opsForValue().set(StrUtil.format(ConstantUtil.MOVEMENT_COMMENT_LIKE, UserHolder.getUser().getId(), commentId), "1");
        return count;
    }

    //取消动态评论点赞
    public Integer movementCommentDisLike(String commentId) {
        // 1组装comment对象
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(commentId));//视频id
        comment.setCommentType(1);//点赞
        comment.setUserId(UserHolder.getUser().getId());

        //2.调用service完成喜欢
        Integer count = commentService.deleteMovementCommentLike(comment);

        //3. 向redis中记录喜欢操作
        stringRedisTemplate.delete(StrUtil.format(ConstantUtil.MOVEMENT_COMMENT_LIKE, UserHolder.getUser().getId(), commentId));
        return count;
    }
}
